"""
工作流服务层
处理工作流的业务逻辑
"""
import json
from typing import List, Optional, Tuple
from datetime import datetime
from sqlalchemy.orm import Session
from sqlalchemy import desc, asc, or_

from models.workflow import Workflow
from models.workflow_instance import WorkflowInstance
from models.workflow_node_execution import WorkflowNodeExecution
from models.workflow_log import WorkflowLog
from schemas.workflow_schema import WorkflowCreate, WorkflowUpdate


class WorkflowService:
    """工作流服务"""

    @staticmethod
    def create_workflow(
        db: Session,
        workflow_create: WorkflowCreate
    ) -> Tuple[bool, str, Optional[Workflow]]:
        """
        创建工作流

        Args:
            db: 数据库会话
            workflow_create: 创建工作流的请求数据

        Returns:
            (是否成功, 错误信息, 工作流对象)
        """
        try:
            # 检查名称是否重复
            existing = db.query(Workflow).filter(
                Workflow.name == workflow_create.name,
                Workflow.deleted_at.is_(None)
            ).first()

            if existing:
                return False, f"工作流名称 '{workflow_create.name}' 已存在", None

            # 验证工作流定义
            workflow_def = workflow_create.workflow_definition.model_dump()
            nodes = workflow_def.get("nodes", [])

            if not nodes:
                return False, "工作流必须至少包含一个节点", None

            # 验证节点ID唯一性
            node_ids = [node.get("id") for node in nodes]
            if len(node_ids) != len(set(node_ids)):
                return False, "节点ID必须唯一", None

            # 创建工作流
            workflow = Workflow(
                name=workflow_create.name,
                description=workflow_create.description,
                workflow_definition=json.dumps(workflow_def),
                cron_expression=workflow_create.cron_expression,
                cron_enabled=workflow_create.cron_enabled,
                status="草稿",
                created_by=workflow_create.created_by
            )

            db.add(workflow)
            db.commit()
            db.refresh(workflow)

            return True, "", workflow

        except Exception as e:
            db.rollback()
            return False, f"创建工作流失败: {str(e)}", None

    @staticmethod
    def get_workflow(db: Session, workflow_id: int) -> Optional[Workflow]:
        """
        获取工作流详情

        Args:
            db: 数据库会话
            workflow_id: 工作流ID

        Returns:
            工作流对象
        """
        return db.query(Workflow).filter(
            Workflow.id == workflow_id,
            Workflow.deleted_at.is_(None)
        ).first()

    @staticmethod
    def list_workflows(
        db: Session,
        page: int = 1,
        page_size: int = 20,
        name: Optional[str] = None,
        status: Optional[str] = None,
        sort_by: str = "created_at",
        order: str = "desc"
    ) -> Tuple[int, List[Workflow]]:
        """
        查询工作流列表

        Args:
            db: 数据库会话
            page: 页码
            page_size: 每页数量
            name: 工作流名称(模糊查询)
            status: 工作流状态
            sort_by: 排序字段
            order: 排序方向

        Returns:
            (总数, 工作流列表)
        """
        query = db.query(Workflow).filter(Workflow.deleted_at.is_(None))

        # 筛选条件
        if name:
            query = query.filter(Workflow.name.contains(name))

        if status:
            query = query.filter(Workflow.status == status)

        # 总数
        total = query.count()

        # 排序
        if sort_by == "name":
            sort_field = Workflow.name
        elif sort_by == "updated_at":
            sort_field = Workflow.updated_at
        else:
            sort_field = Workflow.created_at

        if order == "asc":
            query = query.order_by(asc(sort_field))
        else:
            query = query.order_by(desc(sort_field))

        # 分页
        workflows = query.offset((page - 1) * page_size).limit(page_size).all()

        return total, workflows

    @staticmethod
    def update_workflow(
        db: Session,
        workflow_id: int,
        workflow_update: WorkflowUpdate
    ) -> Tuple[bool, str, Optional[Workflow]]:
        """
        更新工作流

        Args:
            db: 数据库会话
            workflow_id: 工作流ID
            workflow_update: 更新工作流的请求数据

        Returns:
            (是否成功, 错误信息, 工作流对象)
        """
        try:
            workflow = db.query(Workflow).filter(
                Workflow.id == workflow_id,
                Workflow.deleted_at.is_(None)
            ).first()

            if not workflow:
                return False, "工作流不存在", None

            # 检查是否有正在运行的实例
            running_instances = db.query(WorkflowInstance).filter(
                WorkflowInstance.workflow_id == workflow_id,
                WorkflowInstance.status.in_(["运行中", "暂停中", "已暂停"])
            ).count()

            if running_instances > 0:
                return False, "工作流有正在运行的实例,无法修改", None

            # 更新字段
            if workflow_update.name is not None:
                # 检查名称是否重复
                existing = db.query(Workflow).filter(
                    Workflow.name == workflow_update.name,
                    Workflow.id != workflow_id,
                    Workflow.deleted_at.is_(None)
                ).first()
                if existing:
                    return False, f"工作流名称 '{workflow_update.name}' 已存在", None
                workflow.name = workflow_update.name

            if workflow_update.description is not None:
                workflow.description = workflow_update.description

            if workflow_update.workflow_definition is not None:
                workflow_def = workflow_update.workflow_definition.model_dump()
                workflow.workflow_definition = json.dumps(workflow_def)

            if workflow_update.cron_expression is not None:
                workflow.cron_expression = workflow_update.cron_expression

            if workflow_update.cron_enabled is not None:
                workflow.cron_enabled = workflow_update.cron_enabled

            workflow.updated_at = datetime.now()

            db.commit()
            db.refresh(workflow)

            return True, "", workflow

        except Exception as e:
            db.rollback()
            return False, f"更新工作流失败: {str(e)}", None

    @staticmethod
    def delete_workflow(
        db: Session,
        workflow_id: int
    ) -> Tuple[bool, str]:
        """
        删除工作流(软删除)

        Args:
            db: 数据库会话
            workflow_id: 工作流ID

        Returns:
            (是否成功, 错误信息)
        """
        try:
            workflow = db.query(Workflow).filter(
                Workflow.id == workflow_id,
                Workflow.deleted_at.is_(None)
            ).first()

            if not workflow:
                return False, "工作流不存在"

            # 检查是否有关联的实例
            instances_count = db.query(WorkflowInstance).filter(
                WorkflowInstance.workflow_id == workflow_id,
                WorkflowInstance.deleted_at.is_(None)
            ).count()

            if instances_count > 0:
                return False, f"工作流有 {instances_count} 个关联实例,建议先清理实例后再删除"

            # 软删除
            workflow.deleted_at = datetime.now()
            db.commit()

            return True, ""

        except Exception as e:
            db.rollback()
            return False, f"删除工作流失败: {str(e)}"

    @staticmethod
    def get_workflow_instance(
        db: Session,
        instance_id: int
    ) -> Optional[WorkflowInstance]:
        """
        获取工作流实例详情

        Args:
            db: 数据库会话
            instance_id: 实例ID

        Returns:
            工作流实例对象
        """
        return db.query(WorkflowInstance).filter(
            WorkflowInstance.id == instance_id,
            WorkflowInstance.deleted_at.is_(None)
        ).first()

    @staticmethod
    def list_workflow_instances(
        db: Session,
        page: int = 1,
        page_size: int = 20,
        workflow_id: Optional[int] = None,
        status: Optional[str] = None,
        include_not_started: bool = False
    ) -> Tuple[int, List[WorkflowInstance]]:
        """
        查询工作流实例列表

        Args:
            db: 数据库会话
            page: 页码
            page_size: 每页数量
            workflow_id: 工作流ID
            status: 实例状态
            include_not_started: 是否包含"未运行"状态的实例（默认False）

        Returns:
            (总数, 实例列表)
        """
        from services.workflow_engine import WorkflowEngine

        query = db.query(WorkflowInstance).filter(WorkflowInstance.deleted_at.is_(None))

        # 默认过滤掉"未运行"状态的实例（监控面板不显示）
        if not include_not_started:
            query = query.filter(WorkflowInstance.status != WorkflowEngine.STATUS_NOT_STARTED)

        # 筛选条件
        if workflow_id:
            query = query.filter(WorkflowInstance.workflow_id == workflow_id)

        if status:
            query = query.filter(WorkflowInstance.status == status)

        # 总数
        total = query.count()

        # 排序(按创建时间倒序)
        query = query.order_by(desc(WorkflowInstance.created_at))

        # 分页
        instances = query.offset((page - 1) * page_size).limit(page_size).all()

        return total, instances

    @staticmethod
    def get_node_executions(
        db: Session,
        instance_id: int
    ) -> List[WorkflowNodeExecution]:
        """
        获取工作流实例的节点执行记录

        Args:
            db: 数据库会话
            instance_id: 实例ID

        Returns:
            节点执行记录列表
        """
        return db.query(WorkflowNodeExecution).filter(
            WorkflowNodeExecution.workflow_instance_id == instance_id
        ).order_by(WorkflowNodeExecution.started_at).all()

    @staticmethod
    def get_workflow_logs(
        db: Session,
        instance_id: int,
        node_id: Optional[str] = None,
        log_level: Optional[str] = None
    ) -> List[WorkflowLog]:
        """
        获取工作流日志

        Args:
            db: 数据库会话
            instance_id: 实例ID
            node_id: 节点ID(可选)
            log_level: 日志级别(可选)

        Returns:
            日志列表
        """
        query = db.query(WorkflowLog).filter(
            WorkflowLog.workflow_instance_id == instance_id
        )

        if log_level:
            query = query.filter(WorkflowLog.log_level == log_level)

        if node_id:
            # 通过节点ID筛选
            node_executions = db.query(WorkflowNodeExecution).filter(
                WorkflowNodeExecution.workflow_instance_id == instance_id,
                WorkflowNodeExecution.node_id == node_id
            ).all()

            if node_executions:
                execution_ids = [e.id for e in node_executions]
                query = query.filter(WorkflowLog.node_execution_id.in_(execution_ids))

        return query.order_by(WorkflowLog.log_time).all()

    @staticmethod
    def delete_workflow_instance(
        db: Session,
        instance_id: int
    ) -> Tuple[bool, str]:
        """
        删除工作流实例(软删除)

        Args:
            db: 数据库会话
            instance_id: 实例ID

        Returns:
            (是否成功, 错误信息)
        """
        try:
            instance = db.query(WorkflowInstance).filter(
                WorkflowInstance.id == instance_id,
                WorkflowInstance.deleted_at.is_(None)
            ).first()

            if not instance:
                return False, "工作流实例不存在"

            # 检查实例状态,不允许删除正在运行的实例
            if instance.status in ["运行中", "暂停中", "已暂停", "等待中"]:
                return False, f"工作流实例状态为'{instance.status}',无法删除。请先取消或等待实例执行完成。"

            # 软删除
            instance.deleted_at = datetime.now()
            db.commit()

            return True, ""

        except Exception as e:
            db.rollback()
            return False, f"删除工作流实例失败: {str(e)}"
